#include <iostream>
#include <string>
#include <cstring>
#include <functional>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.hpp"
#include "Route.hpp" 
#include "Thread_Pool.hpp"

using func_t = std::function<void(void)>;

int sockfd = 0;
std::string server_ip;
uint16_t server_port = 0;
pthread_t id;

void Recv()
{
    while (true)
    {
        char buffer[1024];
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int m = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
        if (m > 0)
        {
            buffer[m] = 0;
            std::cerr << buffer << std::endl; // 2
        }
    }
}
void Send()
{
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);
    server.sin_addr.s_addr = inet_addr(server_ip.c_str());

    const std::string online = "inline";
    sendto(sockfd, online.c_str(), online.size(), 0, (struct sockaddr *)&server, sizeof(server));

    while (true)
    {
        std::string input;
        std::cout << "Please Enter# "; // 1
        std::getline(std::cin, input); // 0

        int n = sendto(sockfd, input.c_str(), input.size(), 0, (struct sockaddr *)&server, sizeof(server));
        (void)n;
        if (input == "QUIT")
        {
            pthread_cancel(id);
            break;
        }
    }
}

// 发用网络序列。
// // 收
// void Receive()
// {
//     while(true)
//     {
//         char buffer[1024];
//         struct sockaddr_in addr;
//         socklen_t len = sizeof(addr);
//         ssize_t n = recvfrom(socketfd,buffer,sizeof(buffer) - 1,0,(struct sockaddr*)&addr,&len);

//         if(n > 0)
//         {
//             LOG(LogSpace::LogLevel::INFO) << "接收到消息打印。";
//             buffer[n] = 0;
//             std::cout << buffer << std::endl;
//         }
//     }
// }

// // 发。
// void Send()
// {
//     struct sockaddr_in send;
//     // 清零。
//     bzero(&send,sizeof(send));
//     send.sin_family = AF_INET;
//     // 将网络序列转为本地序列。
//     send.sin_port = htons(port);
//     send.sin_addr.s_addr = inet_addr(ip.c_str());

//     while(true)
//     {
//         std::cout << "Please Enter # ";
//         std::string message;
//         std::getline(std::cin,message);
//         sendto(socketfd,message.c_str(),message.size(),0,(const struct sockaddr*)&send,sizeof(send));
//     }
// }

// IP
// port
// 客户端先发后收。
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        LogSpace::Logger::LogMessage(LogSpace::LogLevel::FATAL,"Socket",1,LogSpace::log) << "Argv Fail!";
        return 1;
    }

    std::string ip(argv[1]);
    uint16_t port = std::stoi(argv[2]);

    sockfd = socket(AF_INET,SOCK_DGRAM,0);

    if(sockfd < 0)
    {
        LogSpace::Logger::LogMessage(LogSpace::LogLevel::FATAL,"Socket",1,LogSpace::log) << "Socket Fail!";
        return 2;
    }

    Thread::Thread t1(Send);
    Thread::Thread t2(Recv);

    t1.Start();
    t2.Start();

    t1.Join();
    t2.Join();


    // struct sockaddr_in send;
    // // 清零。
    // bzero(&send,sizeof(send));
    // send.sin_family = AF_INET;
    // // 将网络序列转为本地序列。
    // send.sin_port = ntohs(port);
    // send.sin_addr.s_addr = inet_addr(ip.c_str());

    // 因为发送会造成阻塞，所以我们采用多线程的方式收发，不造成不必要的阻塞。
    // while(true)
    // {
    //     // 发送消息，连接上服务端。需要初始化sockaddr_in
    //     std::string message;
    //     std::cout << "Please Enter #";
    //     std::getline(std::cin,message);
    //     r.MessageRoute(socketfd-,message,addr);

    //     // 收消息。无需初始化sockaddr_in，但是要传长度地址。
    //     char buffer[1024];
    //     struct sockaddr_in receive;
    //     socklen_t len = sizeof(receive);
    //     ssize_t n = recvfrom(socketfd,buffer,sizeof(buffer) - 1,0,(struct sockaddr*)&receive,&len);

    //     if(n > 0)
    //     {
    //         buffer[n] = 0;
    //         std::cout << buffer << std::endl;
    //     }
    // }

    return 0;
}

// // IP
// // port
// int main(int argc,char* argv[])
// {
//     if(argc != 3)
//     {
//         LogSpace::Logger::LogMessage(LogSpace::LogLevel::FATAL,"Socket",1,LogSpace::log) << "Argv Fail!";
//         return 1;
//     }

//     std::string ip(argv[1]);
//     uint16_t port = std::stoi(argv[2]);

//     int socketfd = socket(AF_INET,SOCK_DGRAM,0);

//     if(socketfd < 0)
//     {
//         LogSpace::Logger::LogMessage(LogSpace::LogLevel::FATAL,"Socket",1,LogSpace::log) << "Socket Fail!";
//         return 2;
//     }

//     struct sockaddr_in send;
//     // 清零。
//     bzero(&send,sizeof(send));
//     send.sin_family = AF_INET;
//     // 将网络序列转为本地序列。
//     send.sin_port = ntohs(port);
//     send.sin_addr.s_addr = inet_addr(ip.c_str());

//     while(true)
//     {
//         // 发送消息，连接上服务端。需要初始化sockaddr_in
//         std::string message;
//         std::cout << "Please Enter #";
//         std::getline(std::cin,message);
//         int m = sendto(socketfd,message.c_str(),message.size(),0,(struct sockaddr*)&send,sizeof(send));

//         (void)m;

//         // 收消息。无需初始化sockaddr_in，但是要传长度地址。
//         char buffer[1024];
//         struct sockaddr_in receive;
//         socklen_t len = sizeof(receive);
//         ssize_t n = recvfrom(socketfd,buffer,sizeof(buffer) - 1,0,(struct sockaddr*)&receive,&len);

//         if(n > 0)
//         {
//             buffer[n] = 0;
//             std::cout << buffer << std::endl;
//         }
//     }

//     return 0;
// }